#include "CleanerTask.h"
#include "EmailManager.h"
#include "ConfigValues.h"
#include "Defines.h"
#include "LogManager.h"
#include <process.h>

unsigned __stdcall CleanerTaskThreadProc(LPVOID lpParameter)
{
    HANDLE* hEvent = (HANDLE*)lpParameter;
    time_t lastClearTime = 0;
    while (WaitForSingleObject(*hEvent, 0) != WAIT_OBJECT_0)
    {
        time_t now = time(NULL);
        if ((now - CLEAR_PERIOD) > lastClearTime)
        {
            vector<unsigned int> accounts;
            if (dbLayer->GetAllNotActivatedAccounts(config_cleaner_not_activated_account_period, accounts))
            {
                for (unsigned int i = 0; i < accounts.size(); i++)
                {
                    string szEmailTo;
                    string szEmailBcc;
                    unsigned char ucEmailContentType = CONTENT_TYPE_TEXT_HTML;
                    if (dbLayer->GetAccountEmailInfo(accounts[i], szEmailTo, szEmailBcc, ucEmailContentType))
                    {
                        EmailManager emailManager;
                        VariablesMap variables;
                        stringstream variable;
                        variable << accounts[i];
                        variables.insert(VariablesMapPair("[%account_id%]", variable.str()));
                        string szEmailBody;
                        string szEmailSender;
                        vector<string> recipients;
                        if (emailManager.CreateEmailOnDemand(0, accounts[i], ucEmailContentType, "", szEmailTo, "", szEmailBcc, variables, "account_deletion", "", "", szEmailBody, szEmailSender, recipients))
                        {
                            LOGT(("CleanerTaskThreadProc. Delete account notificate email created\n"));
                            if (dbLayer->SaveEmailToStorage(0, accounts[i], szEmailSender, recipients, -1, 0, szEmailBody, config_db_compress_emails))
                            {
                                LOGT(("CleanerTaskThreadProc. Save email content to DB completed\n"));
                                dbLayer->DeleteAccount(accounts[i]);
                            }
                        }
                    }
                }
            }            

            vector<accountid_monitorid> monitors;
            if (dbLayer->GetAllNotActivatedMonitors(config_cleaner_not_activated_monitor_period, monitors))
            {
                for (unsigned int i = 0; i < monitors.size(); i++)
                {
                    string szEmailTo;
                    string szEmailBcc;
                    string szUrl;
                    string szTitle;
                    unsigned char ucEmailContentType = CONTENT_TYPE_TEXT_HTML;
                    if (dbLayer->GetAccountEmailInfo(monitors[i].first, szEmailTo, szEmailBcc, ucEmailContentType) &&
                        dbLayer->GetMonitorTitleInfo(monitors[i].second, szUrl, szTitle))
                    {
                        EmailManager emailManager;
                        VariablesMap variables;
                        stringstream variable;
                        variable << monitors[i].first;
                        variables.insert(VariablesMapPair("[%account_id%]", variable.str()));
                        variable.str("");
                        variable << monitors[i].second;
                        variables.insert(VariablesMapPair("[%monitor_id%]", variable.str()));
                        variables.insert(VariablesMapPair("[%monitor_title%]", szTitle));
                        variables.insert(VariablesMapPair("[%monitor_url%]", szUrl));
                        string szEmailBody;
                        string szEmailSender;
                        vector<string> recipients;
                        if (emailManager.CreateEmailOnDemand(monitors[i].second, monitors[i].first, ucEmailContentType, "", szEmailTo, "", szEmailBcc, variables, "monitor_deletion", "", "", szEmailBody, szEmailSender, recipients))
                        {
                            LOGT(("CleanerTaskThreadProc. Delete monitor notificate email created\n"));
                            if (dbLayer->SaveEmailToStorage(monitors[i].second, monitors[i].first, szEmailSender, recipients, -1, 0, szEmailBody, config_db_compress_emails))
                            {
                                LOGT(("CleanerTaskThreadProc. Save email content to DB completed\n"));
                                dbLayer->DeleteMonitor(monitors[i].second);
                            }
                        }
                    }
                }
            }            

            dbLayer->ClearEmailStorage(config_cleaner_email_storage_period);

            lastClearTime = now;
        }
        Sleep(SLEEP_WHEN_NOTHING);
    }
    LOGT(("EmailSenderThreadProc. Execution completed\n"));
    return 0;
}

CleanerTask::CleanerTask(void)
{
    hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
}

CleanerTask::~CleanerTask(void)
{
    CloseHandle(hEvent);
}

void CleanerTask::InitTask()
{
    for (unsigned long i=0; i<config_emailsender_threads_count; i++)
    {
        unsigned int uiThreadID = 0;
        HANDLE hThread = (HANDLE)_beginthreadex(NULL, 0, &CleanerTaskThreadProc, &hEvent, CREATE_SUSPENDED, &uiThreadID);
        if (!hThread)
        {
            LOGT(("CleanerTask::InitTask. Thread creation fail\n"));
        }
        else
        {
            threads.insert(ThreadListPair(uiThreadID, hThread));
            LOGT(("CleanerTask::InitTask. Thread created. ThreadID: %u. ThreadHandle 0x%04X\n", uiThreadID, hThread));
        }
    }
}

void CleanerTask::StartTask()
{
    for (ThreadListIter i=threads.begin(); i!=threads.end(); i++)
    {
        if (ResumeThread(i->second) == (DWORD)-1)
        {
            LOGT(("CleanerTask::StartTask. Thread not started. ThreadID: %u. ThreadHandle 0x%04X\n", i->first, i->second));
        }
        else
        {
            LOGT(("CleanerTask::StartTask. Thread started. ThreadID: %u. ThreadHandle 0x%04X\n", i->first, i->second));
        }
    }
}

void CleanerTask::StopTask()
{
    SetEvent(hEvent);
    LOGT(("CleanerTask::StopTask. Send signal to threads for stopping\n"));
}

void CleanerTask::WaitForStop()
{
    for (ThreadListIter i=threads.begin(); i!=threads.end(); i++)
    {
        if (WaitForSingleObject(i->second, INFINITE) == WAIT_OBJECT_0)
        {
            LOGT(("CleanerTask::WaitForStop. Handle closed. ThreadID: %u. ThreadHandle 0x%04X\n", i->first, i->second));
            CloseHandle(i->second);
        }
    }
    threads.clear();
}